import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui show Image, ImageByteFormat;

import 'package:calendar_date_picker2/calendar_date_picker2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_svg/svg.dart';
import 'package:image_picker/image_picker.dart';
import 'package:travel/model/share.dart';
import 'package:travel/screen/flutter_screenutil.dart';
import 'package:travel/ui/all_comment.dart';
import 'package:travel/ui/custom_tabbar.dart';
import 'package:travel/ui/custom_tap.dart';
import 'package:travel/utils/styles.dart';

import 'colors.dart';

class ToolsUtils {
  ToolsUtils._();

  static TextEditingController editingController(String content) {
    TextEditingController textEditingController = TextEditingController(text: content);
    textEditingController.value = TextEditingValue(
        text: content,
        selection: TextSelection.fromPosition(
            TextPosition(affinity: TextAffinity.downstream, offset: content.length)));
    return textEditingController;
  }

  static SvgPicture assetImageSvg(
    String assetName, {
    BoxFit fit = BoxFit.cover,
    double? width,
    double? height,
  }) {
    if (!assetName.endsWith('.svg')) {
      assetName = '$assetName.svg';
    }
    return SvgPicture.asset(
      'assets/svgs/$assetName',
      width: width,
      height: height,
      fit: fit,
    );
  }

  static SvgPicture urlSvg(String url,
      {double? width, double? height, BoxFit fit = BoxFit.contain}) {
    return SvgPicture.network(url, width: width, height: height, fit: fit);
  }

  static AssetImage assetImageIcon(String assetName) {
    return AssetImage('assets/images/icon/$assetName');
  }

  static Image image(
    String assetName, {
    BoxFit? fit,
    double? width,
    double? height,
  }) {
    return Image.asset(
      'assets/images/$assetName',
      fit: fit,
      width: width,
      height: height,
    );
  }

  static AssetImage assetImage(String assetName) {
    return AssetImage(
      'assets/images/$assetName',
    );
  }

  static String getImgPath(String name, {String format = 'png'}) {
    return 'assets/images/$name.$format';
  }

  static ClientTabBar getClientTabBar(List<String> tabs, TabController controller,
      {Color backgroundColor = Colors.transparent,
      ValueChanged<int>? onTap,
      TabBarIndicatorSize? indicatorSize,
      bool? isScrollable}) {
    return ClientTabBar(
      tabs: tabs.map((e) {
        return Tab(
          text: e,
        );
      }).toList(),
      controller: controller,
      indicatorSize: indicatorSize ?? TabBarIndicatorSize.label,
      isScrollable: isScrollable ?? true,
      padding: EdgeInsets.zero,
      indicator: RRecTabIndicator(
          radius: 1,
          insets: EdgeInsets.only(bottom: 5.w),
          color: ColorsUtils.parseColorFromHexString(ColorsUtils.color3478)),
      indicatorMinWidth: 36,
      indicatorWeight: 2,
      labelColor: ColorsUtils.parseColorFromHexString(ColorsUtils.color3333),
      labelStyle: StylesUtils.customTextStyle(fontSize: 15.sp, fontWeight: FontWeight.w700),
      unselectedLabelColor: ColorsUtils.parseColorFromHexString(ColorsUtils.color3333),
      unselectedLabelStyle: StylesUtils.customTextStyle(fontSize: 15.sp),
      backgroundColor: backgroundColor,
      onTap: onTap,
    );
  }

  ///value: 文本内容；fontSize : 文字的大小；fontWeight：文字权重；maxWidth：文本框的最大宽度；maxLines：文本支持最大多少行
  static double calculateTextHeight(BuildContext context, String value, FontWeight fontWeight,
      fontSize, double maxWidth, int maxLines) {
    if (value.isEmpty) {
      return 0.0;
    }
    TextPainter painter = TextPainter(
      locale: Localizations.localeOf(context),
      maxLines: maxLines,
      textDirection: TextDirection.ltr,
      text: TextSpan(
        text: value,
        style: TextStyle(
          fontSize: fontSize,
          fontWeight: fontWeight,
        ),
      ),
    );
    painter.layout(maxWidth: maxWidth);
    return painter.width;
  }

  static double max(double m1, double m2) {
    return m1 > m2 ? m1 : m2;
  }

  static double min(double m1, double m2) {
    return m1 > m2 ? m2 : m1;
  }

  static Future<List<XFile>> loadGalleryImage() async {
    final ImagePicker picker = ImagePicker();
    return await picker.pickMultiImage();
  }

  /// 拍照
  static Future<XFile?> cameraImage() async {
    final picker = ImagePicker();
    return await picker.pickImage(
      source: ImageSource.camera,
    );
  }

  /// 相册选取
  static Future<XFile?> galleryImage() async {
    final picker = ImagePicker();
    return await picker.pickImage(source: ImageSource.gallery);
  }

  static List<ShareModel> shareData() {
    return [
      ShareModel(name: '微信好友', img: 'u4002.svg'),
      ShareModel(name: '微信朋友圈', img: 'u4003.svg'),
      ShareModel(name: 'QQ好友', img: 'u4004.svg'),
      ShareModel(name: 'QQ空间', img: 'u4005.svg'),
    ];
  }

  static Future<int?> openShare(BuildContext context) async {
    List<ShareModel> data = shareData();
    return showModalBottomSheet<int>(
        context: context,
        useSafeArea: true,
        builder: (BuildContext context) {
          return Container(
            height: 150.h,
            padding: EdgeInsets.only(top: 15.h),
            decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(10.w), topRight: Radius.circular(10.w))),
            child: Column(
              children: [
                StaggeredGrid.count(
                    crossAxisCount: 4,
                    mainAxisSpacing: 5.h,
                    children: data
                        .asMap()
                        .map((index, row) => MapEntry(
                            index,
                            InkWell(
                              onTap: () {
                                Navigator.of(context).pop(index);
                              },
                              child: Column(
                                children: [
                                  Center(
                                    child: ToolsUtils.assetImageSvg(row.img,
                                        width: 55.h, height: 55.h),
                                  ),
                                  Container(
                                    alignment: Alignment.center,
                                    margin: EdgeInsets.only(top: 5.h),
                                    child: Text(
                                      row.name,
                                      style: StylesUtils.customTextStyle(
                                          fontSize: 12.sp, color: ColorsUtils.color3333),
                                    ),
                                  )
                                ],
                              ),
                            )))
                        .values
                        .toList()),
                Container(
                    height: 50.h,
                    alignment: Alignment.center,
                    child: TextButton(
                      onPressed: () {
                        Navigator.of(context).pop(-1);
                      },
                      child: Text(
                        '取消',
                        style: StylesUtils.customTextStyle(
                            fontSize: 17.sp, color: ColorsUtils.color3333),
                      ),
                    ))
              ],
            ),
          );
        });
  }

  /// 全部评论
  static void openAllComment(BuildContext context,
      {TextEditingController? controller, ValueChanged<String>? onSubmitted}) {
    showDialog<int>(
      context: context,
      barrierDismissible: true,
      builder: (BuildContext context) {
        return AllComment(controller: controller, onSubmitted: onSubmitted);
      },
    );
  }

  //创建一个新的GestureDetector，用我们自定义的 CustomTapGestureRecognizer 替换默认的
  static RawGestureDetector customGestureDetector({
    GestureTapCallback? onTap,
    GestureTapDownCallback? onTapDown,
    Widget? child,
  }) {
    return RawGestureDetector(
      gestures: {
        CustomTapGestureRecognizer:
            GestureRecognizerFactoryWithHandlers<CustomTapGestureRecognizer>(
          () => CustomTapGestureRecognizer(),
          (detector) {
            detector.onTap = onTap;
          },
        )
      },
      child: child,
    );
  }

  static Future<List<DateTime?>?> showCalendarDatePickerDialog({
    required BuildContext context,
    required CalendarDatePicker2WithActionButtonsConfig config,
    required Size dialogSize,
    List<DateTime?> value = const [],
    BorderRadius? borderRadius,
    bool useRootNavigator = true,
    bool barrierDismissible = true,
    Color? barrierColor = Colors.black54,
    bool useSafeArea = true,
    Color? dialogBackgroundColor,
    RouteSettings? routeSettings,
    String? barrierLabel,
    TransitionBuilder? builder,
  }) async {
    var dialog = Dialog(
      insetPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
      backgroundColor: dialogBackgroundColor ?? Theme.of(context).canvasColor,
      shape: RoundedRectangleBorder(
        borderRadius: borderRadius ?? BorderRadius.circular(10),
      ),
      clipBehavior: Clip.antiAlias,
      child: Container(
        width: dialogSize.width,
        height: max(dialogSize.height, 410),
        color: dialogBackgroundColor,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CalendarDatePicker2WithActionButtons(
              value: value,
              config: config.copyWith(openedFromDialog: true),
            ),
          ],
        ),
      ),
    );
    return showDialog<List<DateTime?>>(
      context: context,
      useRootNavigator: useRootNavigator,
      routeSettings: routeSettings,
      builder: (BuildContext context) {
        return builder == null ? dialog : builder(context, dialog);
      },
      barrierDismissible: barrierDismissible,
      barrierColor: barrierColor,
      barrierLabel: barrierLabel,
      useSafeArea: useSafeArea,
    );
  }

  static Future<ByteData?> widgetToImage(Widget widget,
      {Alignment alignment = Alignment.center,
      Size size = const Size(double.maxFinite, double.maxFinite),
      double devicePixelRatio = 1.0,
      double pixelRatio = 1.0}) async {
    RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();

    RenderView renderView = RenderView(
      child: RenderPositionedBox(alignment: alignment, child: repaintBoundary),
      configuration: ViewConfiguration(
        // size: size,
        devicePixelRatio: devicePixelRatio,
      ),
      view: WidgetsBinding.instance.platformDispatcher.views.first,
      // window: ui.window,
    );

    PipelineOwner pipelineOwner = PipelineOwner();
    pipelineOwner.rootNode = renderView;
    renderView.prepareInitialFrame();

    BuildOwner buildOwner = BuildOwner(focusManager: FocusManager());
    RenderObjectToWidgetElement rootElement = RenderObjectToWidgetAdapter(
      container: repaintBoundary,
      child: widget,
    ).attachToRenderTree(buildOwner);
    buildOwner.buildScope(rootElement);
    buildOwner.finalizeTree();

    pipelineOwner.flushLayout();
    pipelineOwner.flushCompositingBits();
    pipelineOwner.flushPaint();

    ui.Image image = await repaintBoundary.toImage(pixelRatio: pixelRatio);
    ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);

    return byteData;
  }

  static Future<ui.Image> loadImageByProvider(
    ImageProvider provider, {
    ImageConfiguration config = ImageConfiguration.empty,
  }) async {
    Completer<ui.Image> completer = Completer<ui.Image>(); //完成的回调
    ImageStream stream = provider.resolve(config); //获取图片流
    ImageStreamListener listener = ImageStreamListener((ImageInfo frame, bool sync) {
      //监听
      final ui.Image image = frame.image;
      completer.complete(image); //完成
    });
    stream.addListener(listener); //添加监听
    stream.removeListener(listener); //移除监听
    return completer.future; //返回
  }
}
